/*
* Copyright (c) 20016-2020, Chengdu RST technology co., ltd
*
* Change Logs:
* Date           Author       Notes
* 2020-11-30     heyuanhang       the first version
* 2020-01-22     shijiabao        v1.1 增加有关多链接的接口api
*/
#define LOG_TAG     "AT"
#include <COMMON_HEADER/common_header.h>

struct lte_data_struct lte_data = {0,0,0,0,{0}};

extern char registration_package[20];
extern uint8_t connnect_number;

/* 串口接收消息结构定义*/
struct thread_register_msg
{
    uint8_t channel;
};

/* 消息队列控制块 */
static struct rt_messagequeue thread_register_rx_mq;

static char thread_register_pool[128];

at_response_t lte_resp = RT_NULL;
extern uint8_t led_connect_status;

int connect_channel_data = 0;

//端口号
char port0[2] = {0};
char port1[2] = {0};
char port2[2] = {0};
char port3[2] = {0};
char port4[2] = {0};
/* 宏定义TCP指令参数 */
#define TCP_INPUT_TYPE               "TCP"
#define TCP_IP_ADDRESS               "110.191.213.102"
#define TCP_IP_PORT                  9008

/* 宏定义MQTT指令参数 */
#define MQTT_CLIENT_NAME             "rst"
#define MQTT_CLIENT_INDEX            0
#define MQTT_IP_ADDRESS              "\"tcp://mq.tongxinmao.com:18830\""
#define MQTT_KPALIVE_TIME            60
#define MQTT_CLEAN_SESSION           1
#define MQTT_SUB_TOPIC               /public/TEST/#
#define MQTT_PUB_TOPIC               /public/TEST/webcli

/* 宏定义APN指令参数 */
#define APN_PDP_DEFINE               1
#define APN_INDICATE_TYPE            1
#define APN_PASSWORD                 "123456"
#define APN_USER                     "460111139489858@epos.vpdn.sh"
#define APN_PDP_STATUS               1
#define APN_PDP_TYPE1                "IP"
#define APN_PDP_TYPE2                "PPP"
#define APN_PDP_TYPE3                "IPV4"
#define APN_PDP_TYPE4                "IPV4V6"
#define APN_MODE                     1

#define  LET_KEY  0
#define  LET_RST  24

void register_messagequeue_init(void)
{
    /* 初始化消息队列 */
    rt_mq_init(&thread_register_rx_mq, "thread_register_rx_mq",
                thread_register_pool,                 /* 存放消息的缓冲区 */
               sizeof(struct thread_register_msg),    /* 一条消息的最大长度 */
               sizeof(thread_register_pool),         /* 存放消息的缓冲区大小 */
               RT_IPC_FLAG_FIFO);        /* 如果有多个线程等待，按照先来先得到的方法分配消息 */
}

static void urc_datacenter_connect(struct at_client *client, const char *data, rt_size_t size)
{
    int chanel_int = 0;
    int status_int = 0;

    struct thread_register_msg msg;
    rt_err_t result;

    sscanf(data,"+CIPOPEN: %d,%d\n",&chanel_int,&status_int);

    if( status_int == 0 && chanel_int >=0)
    {
        connnect_number = 0;
        lte_data.channel_connect_flag[chanel_int] = 1;
        led_connect_status_change(1);
        if(chanel_int == 0)
        {
            LOG_I("云平台数据中心连接成功");
        }
        else
        {
            LOG_I("透传中心%d连接成功 ",chanel_int);
            msg.channel = chanel_int;
            result = rt_mq_send(&thread_register_rx_mq, &msg, sizeof(msg));
            if ( result == -RT_EFULL)
            {
                /* 消息队列满 */
                LOG_E("message queue full！\n");
            }
        }
    }
}

static void urc_channel_recv(struct at_client *client, const char *data, rt_size_t size)
{
    char port0_str[5] = {0};
    char port1_str[5] = {0};
    char port2_str[5] = {0};

    uint16_t port0_int = 0;
    uint16_t port1_int = 0;
    uint16_t port2_int = 0;

    port0_int = (port0[0]+port0[1]*256);
    port1_int = (port1[0]+port1[1]*256);
    port2_int = (port2[0]+port2[1]*256);

    itoa(port0_int, port0_str, 10);
    itoa(port1_int, port1_str, 10);
    itoa(port2_int, port2_str, 10);

    if((strstr(data, port0_str) ? 1 : 0) && lte_data.channel_connect_flag[0] == 1)
    {
        connect_channel_data = 0;
    }
    else if((strstr(data, port1_str) ? 1 : 0) && lte_data.channel_connect_flag[1] == 1)
    {
        connect_channel_data = 1;
    }
    else if((strstr(data, port2_str) ? 1 : 0) && lte_data.channel_connect_flag[2] == 1)
    {
        connect_channel_data = 2;
    }
    else
    {
        connect_channel_data = -1;
    }
}

/**
 * 函数功能 接收AT_client URC数据，并转发给485与232串口
 * @param data
 * @param size
 */
static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size)
{
    char *recv_lte_buf = NULL;
    int recv_data_size = 0;
    rt_int32_t timeout;

    RT_ASSERT(data && size);

    sscanf(data,"+IPD%d\n",&recv_data_size);
    timeout = recv_data_size > 10 ? recv_data_size : 10;

    recv_lte_buf = (char*)malloc(recv_data_size);

    at_client_recv(recv_lte_buf,recv_data_size,timeout);

    LOG_D("接收到数据:%d", recv_data_size);
#if P_EN==1
    rt_kprintf("recv_data:");
    rt_kprintf("%s",recv_lte_buf);
    rt_kprintf("\n");
#endif
    if(connect_channel_data == 0)
    {
        LOG_D("接收到云平台数据中心数据:%s", recv_lte_buf);
        LOG_I("接收到云平台数据中心数据");
    }
    else if(connect_channel_data == 1)
    {
        //LOG_D("接收到透传中心1数据:%s",recv_lte_buf);
        LOG_I("接收到透传中心1数据");
        rs485_uart_write(recv_lte_buf,recv_data_size);
     //   rs232_uart_write(recv_lte_buf,recv_data_size);
    }
    else if(connect_channel_data == 2)
    {
        LOG_D("接收到透传中心2数据:%s", recv_lte_buf);
        LOG_I("接收到透传中心2数据");
        rs485_uart_write(recv_lte_buf,recv_data_size);
       // rs232_uart_write(recv_lte_buf,recv_data_size);
    }
    else
    {
        LOG_D("接收到未知通道的数据:%s", recv_lte_buf);
        LOG_I("接收到未知通道的数据", recv_lte_buf);
        rs485_uart_write(recv_lte_buf,recv_data_size);
       // rs232_uart_write(recv_lte_buf,recv_data_size);
    }
    free(recv_lte_buf);
}

/**
 * 函数功能 通道0服务器断开链接
 * @param data
 * @param size
 */
static void urc_channel0_offline_func(struct at_client *client,const char *data, rt_size_t size)
{
    //关闭端口与服务器的链接
    lte_data.channel_connect_flag[0] = 0;
    led_connect_status_change(2);
    LOG_I("通道0断线");
}

/**
 * 函数功能 通道1服务器断开链接
 * @param data
 * @param size
 */
static void urc_channel1_offline_func(struct at_client *client,const char *data, rt_size_t size)
{
    //关闭端口与服务器的链接
    lte_data.channel_connect_flag[1] = 0;
    led_connect_status_change(2);
    LOG_I("通道1断线");
}

/**
 * 函数功能 通道2服务器断开链接
 * @param data
 * @param size
 */
static void urc_channel2_offline_func(struct at_client *client,const char *data, rt_size_t size)
{
    //关闭端口与服务器的链接
    lte_data.channel_connect_flag[2] = 0;
    led_connect_status_change(2);
    LOG_I("通道2断线");
}

/**
 * 函数功能 通道3服务器断开链接
 * @param data
 * @param size
 */
static void urc_channel3_offline_func(struct at_client *client,const char *data, rt_size_t size)
{
    //关闭端口与服务器的链接
    lte_data.channel_connect_flag[3] = 0;
    led_connect_status_change(2);
    LOG_I("通道3断线");
}

/**
 * 函数功能 通道4服务器断开链接
 * @param data
 * @param size
 */
static void urc_channel4_offline_func(struct at_client *client,const char *data, rt_size_t size)
{
    //关闭端口与服务器的链接
    lte_data.channel_connect_flag[4] = 0;
    led_connect_status_change(2);
    LOG_I("通道4断线");
}



/*
 * 创建URC结构体
 */
static struct at_urc lte_a7600_urc[] = {
        {"RECV FROM",           "\n",urc_channel_recv},
        {"+IPD",                "\n",urc_recv_func},
        {"+CIPOPEN:",            "\n",urc_datacenter_connect},
        {"+IPCLOSE: 0,1",     "\r\n", urc_channel0_offline_func},
        {"+IPCLOSE: 1,1",     "\r\n", urc_channel1_offline_func },
        {"+IPCLOSE: 2,1",     "\r\n", urc_channel2_offline_func },
        {"+IPCLOSE: 3,1",     "\r\n", urc_channel3_offline_func },
        {"+IPCLOSE: 4,1",     "\r\n", urc_channel4_offline_func },
};

/**
 * 函数功能：发送通用的AT指令进行连接前的测试
 *
 * @param
 */
rt_uint8_t lte_init(void)
{
    LOG_D("1.close reply show:ATE0");
#if P_EN==1
     rt_kprintf("1.close reply show:ATE0\n");
#endif
    if(!lte_send_cmd("ATE0", "OK" , 2, 2))
    {
        lte_data.lte_err_flag = 2;
        return 0;
    }
    rt_thread_mdelay(3000);

    LOG_D("2.communication test:AT");
#if P_EN==1
     rt_kprintf("2.communication test:AT\n");
#endif


    if(!lte_send_cmd("AT", "OK", 5, 2))
    {
        lte_data.lte_err_flag = 1;
        return 0;
    }
    rt_thread_mdelay(3000);
    LOG_D("3.Query the PIN:AT+CPIN?");
#if P_EN==1
     rt_kprintf("3.Query the PIN:AT+CPIN?\n");
#endif
    if(!lte_send_cmd("AT+CPIN?", "+CPIN: READY", 2, 3))
    {
        lte_data.lte_err_flag = 3;
        return 0;
    }
    rt_thread_mdelay(3000);
    LOG_D("4.Check signal quality:AT+CSQ");
#if P_EN==1
     rt_kprintf("4.Check signal quality:AT+CSQ\n");
#endif
    if(!lte_send_cmd("AT+CSQ", "+CSQ:", 2, 3))
    {
        lte_data.lte_err_flag = 4;
        return 0;
    }
    rt_thread_mdelay(3000);
    LOG_D("5.Check ESP network registration status:AT+CEREG?");
#if P_EN==1
     rt_kprintf("5.Check ESP network registration status:AT+CEREG?\n");
#endif
    if(!lte_send_cmd("AT+CEREG?", "+CEREG:", 5, 3))
    {
        lte_data.lte_err_flag = 5;
        return 0;
    }
    rt_thread_mdelay(3000);
    if(!lte_send_cmd("AT+CPSI?", "+CPSI", 3, 3))
    {
        lte_data.lte_err_flag = 101;
        return 0;
    }
    return 1;
}

/**
 * 函数功能：单链路链接，需要模块已准备好联网状态，只链接服务器，用于断线或者未连接成功的进行循环连接服务器
 *
 * @param ip_addres     输入需要连接的IP地址
 *        port          输入需要连接的端口号
 *        channel       连接模式通道
 */

rt_uint8_t tcp_single_Link(rt_uint8_t channel,char *ip_addres,int port)
{
    char cmd[50] = {0};

    if(channel == 1 || channel == 2)
    {
        LOG_I("尝试连接透传中心%d",channel);
    }
    else
    {
        LOG_I("尝试连接云平台数据中心");
    }
    sprintf(cmd,"AT+CIPOPEN=%d,\"TCP\",\"%s\",%d",channel,ip_addres,port);

    at_exec_cmd(NULL, cmd);

    return 0;
}

/**
 * 函数功能：此函数用于建立TCP多链接,最多五个链路，如果某链路port的值为0，那么此链路不建立链接
 *
 * @param ip_addres1     输入需要连接的IP地址1
 *        tcp_port1
 *        netmode        连接模式    TCP
 */
rt_uint8_t tcp_multiple_links(void)
{
    LOG_D("set command mode");
    //set command mode
    if(!lte_send_cmd("AT+CIPMODE=0", "OK", 2, 2))
    {
        lte_data.lte_err_flag = 102;
        return 0;
    }
    rt_thread_mdelay(5000);
    LOG_D("open network");
    //open network
    if(!lte_send_cmd("AT+NETOPEN", "+NETOPEN: 0", 3, 4))
    {
        lte_data.lte_err_flag = 103;
        return 0;
    }
    rt_thread_mdelay(2000);
    LOG_D("query ip address");
    //query ip address
    if(!lte_send_cmd("AT+IPADDR", "+IPADDR", 3, 3))
    {
        lte_data.lte_err_flag = 104;
        return 0;
    }
    return 1;
}

/**
 * 函数功能：此函数用于在多链接模式下从某通道发送数据
 *
 * @param channel     需要发送数据的通道号
 *        data_buffer 需要发送的数据的数组指针
 * @return 1 发送成功
 *         2 发送失败
 */
//uint8_t lte_data_send(uint8_t channel,char *data_buffer)
//{
//    char cmd[20] = {0};
//    sprintf(cmd, "AT+CIPSEND=%d,%d\r\n", channel, sizeof(data_buffer));
//    if(lte_send_cmd(cmd, ">", 1))
//    {
//        sprintf(cmd, "+CIPSEND=%d,%d,%d\r\n", channel, sizeof(data_buffer), sizeof(data_buffer));
//        if(lte_send_cmd(data_buffer, cmd, 1))
//        {
//            return 1;
//        }
//    }
//    return 0;
//}

/**
 * 函数功能：退出透传模式
 *
 * @param
 *
 */
//rt_uint8_t TCP_IP_BreakTrans_entry()
//{
//    rt_kprintf("10.Exit transparent mode:+++\r\n");
//    if(!lte_send_cmd("+++", "OK",1))
//    {
//        lte_data.lte_err_flag = 10;
//        return 0;
//    }
//    lte_data.tcp_connect_flag = 0;
//    return 1;
//}

/**
 * 函数功能：此函数用于通过UART2向SIM7600发送AT指令，重回透传模式
 *
 * @param
 *
 */
//rt_uint8_t TCP_IP_RepeatTrans()
//{
//    rt_kprintf("11.Go back to transparent mode:ATO\r\n");
//    if(!lte_send_cmd("ATO\r\n", "CONNECT 115200", 1))
//    {
//        lte_data.lte_err_flag = 11;
//        return 0;
//    }
//    lte_data.tcp_connect_flag = 1;
//    return 1;
//}

/**
 * 函数功能：此函数用于通过串口2向SIM7600发送AT指令，实现TCP/IP断开连接
 *                  透传模式
 * @param
 *
 */
//rt_uint8_t TCP_IP_BreakLink_entry()
//{
//    rt_kprintf("12.Close the connection to the TCP server:AT+CIPCLOSE=0\r\n");
//    if(!lte_send_cmd("AT+CIPCLOSE=0\r\n", "+CIPCLOSE:0",  1))
//    {
//        lte_data.lte_err_flag = 12;
//        return 0;
//    }
//    lte_data.tcp_connect_flag = 0;
//    return 1;
//}

/**
 * 函数功能：此函数用于通过UART2向SIM7600发送AT指令，开启MQTT服务
 *                  与MQTT服务器相连
 *
 *
 * @param       client_index            客户端标志数
 *              client_name             客户端名字
 *              ip_addres               服务器IP地址
 *              keepalive_time          客户端收到两条消息的时间间隔
 *              clean_session           清除标志
 */
rt_uint8_t MQTT_CreateLink_entry(char client_name[],int client_index,char ip_addres[],int keepalive_time,int clean_session)
{
    /* 开启MQTT服务 */
    rt_kprintf("6.Enable the MQTT service:\r\n");
    if(!lte_send_cmd("AT+CMQTTSTART\r\n", "+CMQTTSTART: 0", 2, 1))
    {
        lte_data.lte_err_flag = 13;
        return 0;
    }

    /* 设置一个将连接到MQTT服务器的客户机 */
    rt_kprintf("7.Get a client that will connect to the MQTT server:\r\n");
    char at_mqttname[60];
    rt_sprintf(at_mqttname, "AT+CMQTTACCQ=%d,\"%s\"\r\n",client_index,client_name);
    if(!lte_send_cmd(at_mqttname, "OK", 2,1))
    {
        lte_data.lte_err_flag = 14;
        return 0;
    }

    /* 获取上一步设置的客户端 */
    rt_kprintf("8.Query the client set up in the previous step:\r\n");
    if(!lte_send_cmd("AT+CMQTTACCQ?\r\n", "+CMQTTACCQ:", 2, 1))
    {
        lte_data.lte_err_flag = 15;
        return 0;
    }

    /* 连接到MQTT Server */
    rt_kprintf("9.Connect to MQTT Server:\r\n");
    char at_mqttinst[60];
    rt_sprintf(at_mqttinst, "AT+CMQTTCONNECT=%d,\"%s\",%d,%d\r\n",client_index,ip_addres,keepalive_time,clean_session);
    if(!lte_send_cmd(at_mqttinst, "+CMQTTCONNECT:", 2,1))
    {
        lte_data.lte_err_flag = 16;
        return 0;
    }

    return 1;
}

/**
 * 函数功能：从MQTT Server   订阅主题
 *
 *
 *
 * @param   client_index    客户端标志数
 *          topic_lenth     客户端长度
 *          sub_topic       topic主题
 */
rt_uint8_t MQTT_Subscribe_topic(int client_index,int topic_lenth,char sub_topic[])
{
    /* 从MQTT Server订阅一个topic主题 */
    rt_kprintf("10.Subscribe to a Topic from MQTT Server\r\n");
    char at_subtopic[60];
    rt_sprintf(at_subtopic, "AT+CMQTTSUB=%d,%d,%d\r\n",client_index,topic_lenth,1);
    if(!lte_send_cmd(at_subtopic, ">", 1,1))
    {
        lte_data.lte_err_flag = 17;
        return 0;
    }
    //lte_data.mqtt_connect_flag = 1;

    /* 发送订阅服务的主题 */
    rt_kprintf("11.Enter the topic for the subscription service\r\n");
    char at_sendtopic[60];
    rt_sprintf(at_sendtopic, "%s\r\n",sub_topic);
    if(!lte_send_cmd(at_sendtopic, "+CMQTTSUB: 0,11", 1,1))
    {
        lte_data.lte_err_flag = 18;
        return 0;
    }
    return 1;
}

/**
 * 函数功能：从MQTT Server   发布消息主题
 *
 *
 *
 * @param   client_index        客户端标志数
 *          msg_topiclenth      消息主题长度
 *          mes_topic           消息主题
 */
rt_uint8_t MQTT_Message_topic(int client_index,int msg_topiclenth,char mes_topic[])
{
    /* 设置发布消息的topic主题 */
    rt_kprintf("12.Set the topic of the post message:\r\n");
    char at_msgtopic[60];
    rt_sprintf(at_msgtopic, "AT+CMQTTTOPIC=%d,%d\r\n",client_index,msg_topiclenth);
    if(!lte_send_cmd(at_msgtopic, ">", 1,1))
    {
        lte_data.lte_err_flag = 19;
        return 0;
    }

    /* 发送设置的Publish的主题 */
    rt_kprintf("13.Publish the theme of the Publish Settings\r\n");
    char at_sendmsgtopic[60];
    rt_sprintf(at_sendmsgtopic, "%s\r\n",mes_topic);
    if(!lte_send_cmd(at_sendmsgtopic, "OK", 1,1))
    {
        lte_data.lte_err_flag = 20;
        return 0;
    }
    return 1;
}

/**
 * 函数功能：设置发布消息的有效负载
 *
 *
 * @param   client_index        客户端标志数
 *          set_loadvalue       设置负载的容量
 *          set_load            所要发布的消息
 */
rt_uint8_t MQTT_Messageload(int client_index,int set_loadvalue,char set_load[])
{
    /* 设置发布消息的有效负载 */
    rt_kprintf("14.Sets the payload of the publish message\r\n");
    char at_load[60];
    rt_sprintf(at_load, "AT+CMQTTPAYLOAD=%d,%d\r\n",client_index,set_loadvalue);
    if(!lte_send_cmd(at_load, ">", 1,1))
    {
        lte_data.lte_err_flag = 21;
        return 0;
    }

    /* 设置负载 */
    rt_kprintf("15.Set the load\r\n");
    char at_setload[100];
    rt_sprintf(at_setload, "%s\r\n",set_load);
    if(!lte_send_cmd(at_setload, "OK", 1,1))
    {
        lte_data.lte_err_flag = 22;
        return 0;
    }
    return 1;
}

/**
 * 函数功能：发布一条消息      注：此函数需提前设定好发布消息的负载以及消息的内容
 *
 *
 * @param   client_index            客户端标志数
 *          qos                     消息次数
 *          0                       最多一次
 *          1                       至少一次
 *          2                       只有一次
 *
 *          send_timeout            发布超时时间 60s-180s
 */
rt_uint8_t MQTT_SendMessageOnce(int client_index,int qos,int send_timeout)
{
    /* 发布一条消息 */
    rt_kprintf("16.Post a message\r\n");
    char at_sendmsg[60];
    rt_sprintf(at_sendmsg, "AT+CMQTTPUB=%d,%d,%d\r\n",client_index,qos,send_timeout);
    if(!lte_send_cmd(at_sendmsg, "OK", 1,1))
    {
        lte_data.lte_err_flag = 23;
        return 0;
    }
    return 1;
}

/**
  * 函数功能：从Server订阅一个主题+订阅一条消息
 *
 *
 * @param   client_index        客户端标志数
 *          qos                 消息次数
 *          subtoplenth         主题长度
 *          topicvalue          主题内容
 *
 */
rt_uint8_t MQTT_Subscribe(int client_index,int qos,int subtoplenth,char topicvalue[])
{
    rt_kprintf("17.Set a topic for the subscription message\r\n");
    char at_subtop[60];
    rt_sprintf(at_subtop, "AT+CMQTTSUBTOPIC=%d,%d,%d\r\n",client_index,subtoplenth,qos);
    if(!lte_send_cmd(at_subtop, ">",1,1))
    {
        lte_data.lte_err_flag = 24;
        return 0;
    }

    /* 输入订阅消息的主题 */
    rt_kprintf("18.Enter the topic of the subscription message\r\n");
    char at_setmsgtopic[60];
    rt_sprintf(at_setmsgtopic, "%s\r\n",topicvalue);
    if(!lte_send_cmd(at_setmsgtopic, "OK", 1,1))
    {
        lte_data.lte_err_flag = 25;
        return 0;
    }

    /* 从服务器订阅一条消息 */
    rt_kprintf("19.Subscribe to a message from the server\r\n");
    char at_submsg[60];
    rt_sprintf(at_submsg, "AT+CMQTTSUB=%d\r\n",client_index);
    if(!lte_send_cmd(at_submsg, "OK", 1,1))
    {
        lte_data.lte_err_flag = 26;
        return 0;
    }
    return 1;
}

/**
  * 函数功能：从Server取消订阅一个主题
 *
 *
 * @param   client_index        客户端标志数
 *          calcel_toplenth     取消主题的长度
 *          dup_flag            重新交付时标志消息
 *          topicvalue          输入将要取消的主题
 *
 */
rt_uint8_t MQTT_Canceltopic(int client_index,int calcel_toplenth,int dup_flag,char topicvalue[])
{
    /* 从服务器取消订阅一个主题 */
    rt_kprintf("20.Unsubscribe a topic from the server\r\n");
    char at_calceltop[60];
    rt_sprintf(at_calceltop, "AT+CMQTTUNSUB=%d,%d,%d\r\n",client_index,calcel_toplenth,dup_flag);
    if(!lte_send_cmd(at_calceltop, ">", 1,1))
    {
        lte_data.lte_err_flag = 27;
        return 0;
    }

    /* 输入取消的主题 */
    rt_kprintf("21.Enter a theme to cancel\r\n");
    char at_topvalue[60];
    rt_sprintf(at_topvalue, "%s\r\n",topicvalue);
    if(!lte_send_cmd(at_topvalue, "OK", 1,1))
    {
        lte_data.lte_err_flag = 28;
        return 0;
    }
    return 1;
}

/**
 * 函数功能：此函数用于通过串口2向SIM7600发送AT指令，停止MQTT服务
 *                  与MQTT服务器断开连接
 *
 *
 * @param       client_index    客户端标志数
 *              timeout         断开连接的超时值
 */
rt_uint8_t MQTT_BreakLink_entry(int client_index,int timeout)
{
    /* 断开与MQTT服务器的连接 */
    rt_kprintf("22.Disconnect from the MQTT server:\r\n");
    char at_disconnect[60];
    rt_sprintf(at_disconnect, "AT+CMQTTDISC=%d,%d\r\n",client_index,timeout);
    if(!lte_send_cmd(at_disconnect, "OK", 1,1))
    {
        lte_data.lte_err_flag = 29;
        return 0;
    }

    /* 释放客户端 */
    rt_kprintf("23.Release client\r\n");
    char at_releaseclient[60];
    rt_sprintf(at_releaseclient, "AT+CMQTTREL=%d\r\n",client_index);
    if(!lte_send_cmd(at_releaseclient, "OK", 1,1))
    {
        lte_data.lte_err_flag = 30;
        return 0;
    }

    /* 停止MQTT服务  */
    rt_kprintf("24.Stop the MQTT service\r\n");
    if(!lte_send_cmd("AT+CMQTTSTOP\r\n", "OK", 1,1))
    {
        lte_data.lte_err_flag = 31;
        return 0;
    }
    return 1;
}

/**
 * 函数功能：此函数用于通过串口2向SIM7600发送AT指令，开启APN模式
 *
 *
 *
 * @param   cid                 指定特定的PDP上下文定义       1-15
 *          auth_type           指定上下文的身份验证类型    0(none)，1(PAP)，2(CHAP)
 *          passwd              指定用于身份验证的密码
 *          pdp_state           指定PDP上下文的关闭与激活   0(deactivated),1(activated)
 *          pdp_type            数据协议类型            IP(Internet Protocol),PPP(Point to Point Protocol),
 *                                                IPV6(Internet Protocol Version 6),IPV4V6(Dual PDN Stack)
 *          set_apn             指定移动，联通，电信APN类型，APN接入点
 *          phemode             设置手机的功能
 */
rt_uint8_t APN_CreateLink(int cid,int auth_type,char *passwd,char *user,int pdp_state ,char *pdp_type,char *set_apn,int phemode)
{

    /*打开网络*/
    rt_kprintf("6.Open the network\r\n");
    if(!lte_send_cmd("AT+NETOPEN\r\n", "+NETOPEN: 0", 2,1))
    {
        lte_data.lte_err_flag = 8;
        return 0;
    }

    /* 激活PDP上下文 */
    rt_kprintf("7.Activate the PDP context\r\n");
    char at_context[30];
    rt_sprintf(at_context, "AT+CGACT=%d,%d\r\n",pdp_state,cid);
    if(!lte_send_cmd(at_context, "OK", 5,1))
    {
        lte_data.lte_err_flag = 98;
        return 0;
    }

    /* 查询PDP上下文 */
    rt_kprintf("8.Query the PDP context\r\n");
    if(!lte_send_cmd("AT+CGDCONT?\r\n", "+CGDCONT:", 5,1))
    {
        lte_data.lte_err_flag = 32;
        return 0;
    }

    /* 设置移动APN */
    rt_kprintf("9.Set up the mobile APN\r\n");
    char at_setapn[50];
    rt_sprintf(at_setapn, "AT+CGDCONT=%d,\"%s\",\"%s\"\r\n",cid,pdp_type,set_apn);
    if(!lte_send_cmd(at_setapn,"OK",5,1))
    {
        lte_data.lte_err_flag = 99;
        return 0;
    }

    /* 关闭网络 */
    rt_kprintf("10.Shut down the network\r\n");
    if(!lte_send_cmd("AT+NETCLOSE\r\n", "+NETCLOSE:0", 5,1))
    {
        lte_data.lte_err_flag = 6;
        //return 0;
    }

    /* 设置GPRS的PDP-IP连接的认证类型 */
    rt_kprintf("11.Sets the authentication type for THE PDP-IP connection of GPRS\r\n");
    char at_pdpip[60];
    rt_sprintf(at_pdpip, "AT+CGAUTH=%d,%d,\"%s\",\"%s\"\r\n",cid,auth_type,passwd,user);
    if(!lte_send_cmd(at_pdpip, "OK", 5,1))
    {
        lte_data.lte_err_flag = 33;
        return 0;
    }

    /* 设置手机的功能 */
    rt_kprintf("12.Set the phone's functions\r\n");
    char at_mode[60];
    rt_sprintf(at_mode, "AT+CFUN=%d\r\n",phemode);
    if(!lte_send_cmd(at_mode, "OK", 5,1))
    {
        lte_data.lte_err_flag = 34;
        return 0;
    }

    /* 查询PDP上下文 */
    rt_kprintf("13.Query the PDP context\r\n");
    if(!lte_send_cmd("AT+CGDCONT?\r\n", "+CGDCONT:", 5,1))
    {
        lte_data.lte_err_flag = 32;
        return 0;
    }

    /* 查询GPRS的PDP-IP连接的认证类型 */
    rt_kprintf("14.Query the AUTHENTICATION type of THE PDP-IP connection for GPRS\r\n");
    if(!lte_send_cmd("AT+CGAUTH?\r\n", "+CGAUTH:", 5,1))
    {
        lte_data.lte_err_flag = 35;
        return 0;
    }


    /* 开启网络 */
    rt_kprintf("15.Open the network\r\n");
    if(!lte_send_cmd("AT+NETOPEN\r\n", "OK", 5,1))
    {
        lte_data.lte_err_flag = 8;
        return 0;
    }

    /* 查询套接字PDP地址 */
    rt_kprintf("16.Query the socket PDP address\r\n");
    if(!lte_send_cmd("AT+IPADDR\r\n", "OK", 5,1))
    {
        lte_data.lte_err_flag = 36;
        return 0;
    }

    /* 查询固件的修订标识 */
    rt_kprintf("17.Query the firmware revision identification\r\n");
    if(!lte_send_cmd("AT+CGMR\r\n", "OK", 5,1))
    {
        lte_data.lte_err_flag = 37;
        return 0;
    }

    /* 读取模块的IMEI */
    rt_kprintf("18.Read the IMEI of the module\r\n");
    if(!lte_send_cmd("AT+SIMEI?\r\n", "OK", 5,1))
    {
        lte_data.lte_err_flag = 38;
        return 0;
    }

    /* 获取手机的功能模式 */
    rt_kprintf("19.Get the phone's functional mode\r\n");
    if(!lte_send_cmd("AT+CFUN?\r\n", "OK", 5,1))
    {
        lte_data.lte_err_flag = 39;
        return 0;
    }

    /* 获取ESP网络注册状态 */
    rt_kprintf("20.Gets the ESP network registration status\r\n");
    if(!lte_send_cmd("AT+CEREG?\r\n", "OK", 5,1))
    {
        lte_data.lte_err_flag = 40;
        return 0;
    }
    //lte_data.apn_connect_flag = 1;
    return 1;
}
/**
 * @brief 串口2发送命令
 * @param cmd:命令
 *        res:需要检查的返回指令
 *        renumber:发送命令次数
 * @return
 */
rt_uint8_t lte_send_cmd(char *cmd,char *res,rt_uint8_t renumber,uint8_t line_num)
{
    const char *lte_p = NULL;

    for(int i=0;i<renumber;i++)
    {
       lte_resp = at_resp_set_info(lte_resp,200,line_num, rt_tick_from_millisecond(2000));
       LOG_D("send AT instruction:%s",cmd);
       if(at_exec_cmd(lte_resp, cmd) >= 0)
       {
           if((lte_p = at_resp_get_line_by_kw(lte_resp,res)) != NULL)
            {
                LOG_D("AT instruction reply(successful):%s\n",lte_p);
#if P_EN==1
     rt_kprintf("AT instruction reply(successful):%s\n",lte_p);
#endif
                return 1;
            }
            else
            {
                LOG_D("AT instruction reply(fail):%s\n",lte_p);
            }
       }
       rt_thread_mdelay(1000);
   }
   return 0;
}

/**
 * SIM7600C1模块复位初始化
 */
void lte_reset(void)
{
    //关机
    cat1_4g_power_pin_on();
    rt_thread_mdelay(50);
    cat1_4g_power_pin_down();

    rt_thread_mdelay(3000);
    //开机
    cat1_4g_power_pin_on();
    rt_thread_mdelay(50);
    cat1_4g_power_pin_down();

    if(lte_resp != NULL)
    {
        at_delete_resp(lte_resp);
    }
    lte_resp = at_create_resp(200,0, rt_tick_from_millisecond(5000));
    if(lte_resp == NULL)
    {
        LOG_E("创建lte_resp失败");
    }

    lte_data.lte_err_flag=0;
    lte_data.lte_init_flag=1;
    lte_data.lte_net_flag=0;
}

/**
 * 连接错误检测函数
 *
 */
void tcp_error_function(uint8_t err)
{
    rt_kprintf("Warning: An error has occurred....\r\n");
    switch(err)
    {
      case 1:
          rt_kprintf("AT ERROR\r\n");
      break;

      case 2:
          rt_kprintf("Failed to close echo\r\n");
      break;

      case 3:
          rt_kprintf("Failed to get PIN\r\n");
      break;

      case 4:
          rt_kprintf("Failed to obtain signal quality\r\n");
      break;

      case 5:
          rt_kprintf("Failed to obtain ESP network status\r\n");
      break;

      case 6:
          rt_kprintf("Shutdown network failure\r\n");
      break;

      case 7:
          rt_kprintf("Select transparent mode failed\r\n");
      break;

      case 8:
          rt_kprintf("Failed to open network\r\n");
      break;

      case 9:
          rt_kprintf("Failed to connect to TCP server\r\n");
      break;

      case 10:
          rt_kprintf("Failed to exit transparent mode\r\n");
      break;

      case 11:
          rt_kprintf("Failed to return to transparent mode\r\n");
      break;

      case 12:
          rt_kprintf("Failed to disconnect TCP server\r\n");
      break;

      case 13:
          rt_kprintf("Failed to enable THE MQTT service\r\n");
      break;

      case 14:
          rt_kprintf("Failed to get the client to connect to the MQTT server\r\n");
      break;

      case 15:
          rt_kprintf("Failed to get the client set in the previous step\r\n");
      break;

      case 16:
          rt_kprintf("Failed to connect to MQTT server\r\n");
      break;

      case 17:
          rt_kprintf("Failed to set the subscription topic\r\n");
      break;

      case 18:
          rt_kprintf("Sending a subscription topic failed\r\n");
      break;

      case 19:
          rt_kprintf("Failed to set the message subject\r\n");
      break;

      case 20:
          rt_kprintf("Failed to send message subject\r\n");
      break;

      case 21:
          rt_kprintf("Failed to set the publish message payload\r\n");
      break;

      case 22:
          rt_kprintf("Failed to send set load value\r\n");
      break;

      case 23:
          rt_kprintf("Failed to publish a message\r\n");
      break;

      case 24:
          rt_kprintf("Failed to enter the topic for the subscription message\r\n");
      break;

      case 25:
          rt_kprintf("The topic to send a subscription message failed\r\n");
      break;

      case 26:
          rt_kprintf("Failed to subscribe a message from the MQTT server\r\n");
      break;

      case 27:
          rt_kprintf("Failed to unsubscribe a topic from the MQTT server\r\n");
      break;

      case 28:
          rt_kprintf("Failed to send a topic to unsubscribe from the MQTT server\r\n");
      break;

      case 29:
          rt_kprintf("Failed to disconnect the MQTT server\r\n");
      break;

      case 30:
          rt_kprintf("Failure to release MQTT client\r\n");
      break;

      case 31:
          rt_kprintf("Failure to stop the MQTT service\r\n");
      break;

      case 32:
          rt_kprintf("Failed to query the PDP context\r\n");
      break;

      case 33:
          rt_kprintf("The authentication type for setting UP THE PDP-IP connection for GPRS failed\r\n");
      break;

      case 34:
          rt_kprintf("Failed to set the phone function\r\n");
      break;

      case 35:
          rt_kprintf("Failed to query the AUTHENTICATION type of THE PDP-IP connection for GPRS\r\n");
      break;

      case 36:
          rt_kprintf("The query for the socket PDP address failed\r\n");
      break;

      case 37:
          rt_kprintf("Failed to query the fix id for the firmware\r\n");
      break;

      case 38:
          rt_kprintf("Failed to read the IMEI of the module\r\n");
      break;

      case 39:
          rt_kprintf("Failed to get the phone's function mode\r\n");
      break;

      case 40:
          rt_kprintf("Failed to obtain ESP network registration status\r\n");
      break;

      case 98:
          rt_kprintf("Failed to activate the PDP context\r\n");

      case 99:
          rt_kprintf("Failed to set the mobile APN\r\n");

      default:
          rt_kprintf("no error:.....................\r\n");
    }
}
rt_uint8_t lte_channel_send_data(rt_uint8_t channel, char *buf, uint32_t size)
{
    char cmd[20] = {0};
    lte_resp = at_resp_set_info(lte_resp,200,1, rt_tick_from_millisecond(2000));

    sprintf(cmd, "AT+CIPSEND=%d,%d",channel, size);
    if(at_exec_cmd(lte_resp, cmd)>=0)
    {
        if(at_resp_get_line_by_kw(lte_resp,">") != NULL)
        {
            LOG_D("data send failed");
            return 1;
        }
    }
    else
    {
        return 1;
    }

    lte_resp = at_resp_set_info(lte_resp,200,2, rt_tick_from_millisecond(2000));
    if(at_exec_cmd(lte_resp, buf)>=0)
    {
        sprintf(cmd, "OK\n+CIPSEND: %d,%d,%d",channel, size, size);
        if(at_resp_get_line_by_kw(lte_resp,cmd) != NULL)
        {
            LOG_D("data send failed");
            return 1;
        }
        else
        {
#if P_EN==1
     rt_kprintf("buf:%s\n",buf);
    for(int i =0;i<size;i++)
    {
        rt_kprintf("%d ",buf[i]);
    }
    rt_kprintf("\n");
#endif
            return 0;
        }
    }
    else
    {
        return 1;
    }
}

void a7600_client_urc_init(void)
{
    /* 添加多种 URC 数据至 URC 列表中，当接收到同时匹配 URC 前缀和后缀的数据，执行 URC 函数  */
    at_set_urc_table(lte_a7600_urc, sizeof(lte_a7600_urc) / sizeof(lte_a7600_urc[0]));
}

void register_thread_entry(void *parameter)
{
    struct thread_register_msg msg;
    rt_err_t result;

    rt_thread_mdelay(10000);

    while(1)
    {
        rt_memset(&msg, 0, sizeof(msg));
                /* 从消息队列中读取消息*/
        result = rt_mq_recv(&thread_register_rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
        if (result == RT_EOK)
        {
            if(!lte_channel_send_data(msg.channel, registration_package, strlen(registration_package)))
            {
                LOG_I("透传中心%d发送注册包成功",msg.channel);
                LOG_D("透传中心%d发送注册包成功:%s",msg.channel, registration_package);
            }
        }
    }

}
